package com.example.siyun.service.impl.loginserviceimpl;

import cn.hutool.core.util.StrUtil;
import com.example.siyun.handle.SmsAuthenticationToken;
import com.example.siyun.util.WebUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Auther: 全
 * @Date: 2022/10/13 09:03
 * @Description:
 */
@Component
public class SmsAuthenticationProvider implements AuthenticationProvider {


    private UserDetailsService userDetailsServiceImpl;

    private RedisTemplate<String, String> redisTemplate;

    public SmsAuthenticationProvider(@Qualifier("smsUserDetailsService") UserDetailsService userDetailsServiceImpl, RedisTemplate<String, String> redisTemplate) {
        this.userDetailsServiceImpl = userDetailsServiceImpl;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsAuthenticationToken authenticationToken = (SmsAuthenticationToken) authentication;
        Object principal = authentication.getPrincipal();// 获取凭证也就是用户的手机号
//        userDetailsServiceImpl.loadUserByUsername(phone);
        System.out.println("手机号");
        System.out.println((String)principal);
        WebUtils.getSession().setAttribute("phone",(String)principal);
        System.out.println("手机号");
        String phone = "";
        if (principal instanceof String) {
            phone = (String) principal;
        }
        String inputCode = (String) authentication.getCredentials(); // 获取输入的验证码
        System.out.println("从前端拿过来的验证码");
        System.out.println(inputCode);
        System.out.println("从前端拿过来的验证码");
        // 1. 检验Redis手机号的验证码
        String redisCode = redisTemplate.opsForValue().get(phone);
        System.out.println("从redis里面获取的验证码");
        System.out.println(redisCode);
        System.out.println("从redis里面获取的验证码");
        if (StrUtil.isEmpty(redisCode)) {
            throw new BadCredentialsException("验证码已经过期或尚未发送，请重新发送验证码");
        }
        if (!inputCode.equals(redisCode)) {
            throw new BadCredentialsException("输入的验证码不正确，请重新输入");
        }
        // 2. 根据手机号查询用户信息
        UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(phone);
        if (userDetails == null) {
            throw new InternalAuthenticationServiceException("phone用户不存在，请注册");
        }
        // 3. 重新创建已认证对象,
        SmsAuthenticationToken authenticationResult = new SmsAuthenticationToken(principal,inputCode, userDetails.getAuthorities());
        authenticationResult.setDetails(authenticationToken.getDetails());
        return authenticationResult;
    }
    @Override
    public boolean supports(Class<?> aClass) {
        return SmsAuthenticationToken.class.isAssignableFrom(aClass);
    }
}
